#pragma once
#include "zMatrixBase.hpp"

//for mat+v or v+mat, one matrix and one scalar

namespace zzz{
///////////////////////////////////////////////////
//Left
#define CONSTANT_LEFT_EXPRESSION(name,ope) \
template<typename T, class Major>\
class zConstantLeft##name##Expression : public zMatrixBaseR<T,Major>\
{\
public:\
  explicit zConstantLeft##name##Expression(const zMatrixBaseR<T,Major>& mat, T v)\
  :zMatrixBaseR<T,Major>(mat.rows_,mat.cols_),Mat_(mat),V_(v){}\
  const T operator()(zuint r, zuint c) const\
  {\
    CheckRange(r, c); \
    return Mat_(r,c) ope V_; \
  }\
public:\
  const zMatrixBaseR<T,Major> &Mat_; \
  const T V_; \
}; \
template<typename T, class Major>\
const zConstantLeft##name##Expression<T,Major> operator ope(const zMatrixBaseR<T,Major>& mat, T v)\
{return zConstantLeft##name##Expression<T,Major>(mat,v);}

CONSTANT_LEFT_EXPRESSION(Plus,+)
CONSTANT_LEFT_EXPRESSION(Minus,-)
CONSTANT_LEFT_EXPRESSION(Times,*)
CONSTANT_LEFT_EXPRESSION(DividedBy,/)

CONSTANT_LEFT_EXPRESSION(EQ,==)
CONSTANT_LEFT_EXPRESSION(NE,!=)
CONSTANT_LEFT_EXPRESSION(LT,<)
CONSTANT_LEFT_EXPRESSION(LE,<=)
CONSTANT_LEFT_EXPRESSION(GT,>)
CONSTANT_LEFT_EXPRESSION(GE,>=)

///////////////////////////////////////////////////
//Right
#define CONSTANT_RIGHT_EXPRESSION(name,ope) \
template<typename T,class Major>\
class zConstantRight##name##Expression : public zMatrixBaseR<T,Major>\
{\
public:\
  explicit zConstantRight##name##Expression(const zMatrixBaseR<T,Major>& mat, T v)\
  :zMatrixBaseR<T,Major>(mat.rows_,mat.cols_),Mat_(mat),V_(v){}\
  using zMatrixBaseR<T,Major>::operator(); \
  const T operator()(zuint r, zuint c) const\
  {\
    CheckRange(r, c); \
    return V_ ope Mat_(r,c); \
  }\
public:\
  const zMatrixBaseR<T,Major> &Mat_; \
  const T V_; \
}; \
template<typename T,class Major>\
const zConstantRight##name##Expression<T,Major> operator ope(T v, const zMatrixBaseR<T,Major>& mat)\
{return zConstantRight##name##Expression<T,Major>(mat,v);}

CONSTANT_RIGHT_EXPRESSION(Plus,+)
CONSTANT_RIGHT_EXPRESSION(Minus,-)
CONSTANT_RIGHT_EXPRESSION(Times,*)
CONSTANT_RIGHT_EXPRESSION(DividedBy,/)

CONSTANT_RIGHT_EXPRESSION(EQ,==)
CONSTANT_RIGHT_EXPRESSION(NE,!=)
CONSTANT_RIGHT_EXPRESSION(LT,<)
CONSTANT_RIGHT_EXPRESSION(LE,<=)
CONSTANT_RIGHT_EXPRESSION(GT,>)
CONSTANT_RIGHT_EXPRESSION(GE,>=)

}
